package servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import core.Core;
import core.Crop;
import values.*;
import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.detector.MagicMimeMimeDetector;
import exception.ParameterException;
import exception.ServerDownException;

public class Gente extends HttpServlet
{
	// Constants
	/**
	 * Generated serial.
	 */
	private static final long serialVersionUID = 3633668443789579958L;
	
	/**
	 * Index page url.
	 */
	private static final String INDEX = "http://50.56.220.110:8080/gente/bancos";
	
	/**
	 * Maximum upload size in bytes.
	 */
	private static final int MAX_FILE_SIZE = 6291456;
	
	/**
	 * Maximum upload size per file in bytes.
	 */
	private static final int MAX_UPLOAD_SIZE = 5242880;
	
	/**
	 * Default user's photo.
	 */
	public static final String DEFAULT_PHOTO = "default.png";
	
	
	/**
	 * Parameter name, function.
	 */
	public static final String FUNCTION = "fnc";
	
	/**
	 * Parameter name, logIn.
	 */
	public static final String LOGIN = "email";
	
	/**
	 * Parameter name, password.
	 */
	private static final String PASSWORD = "password";
	
	/**
	 * Parameter name, first name.
	 */
	public static final String FIRST_NAME = "firstName";
	
	/**
	 * Parameter name, last name.
	 */
	public static final String LAST_NAME = "lastName";
	
	/**
	 * Parameter name, alias.
	 */
	public static final String ALIAS = "alias";
	
	/**
	 * Parameter name, photo.
	 */
	public static final String PHOTO = "photo";
	
	
	/**
	 * Servlet function, authenticate.
	 */
	private static final String AUTHENTICATE  = "verify";
	
	/**
	 * Servlet function, check login.
	 */
	private static final String CHECK_LOGIN = "checkLogin";
	
	/**
	 * Servlet function, check alias.
	 */
	private static final String CHECK_ALIAS = "checkAlias";
	
	/**
	 * Servlet response, ok.
	 */
	private static final String OK = "ok";
	
	/**
	 * Servlet response, negative.
	 */
	private static final String NEGATIVE = "bad";
	
	// Methods
	/**
	 * Resolves GET request with q parameter.
	 */
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException 
    {
		request.getSession().invalidate();
		response.sendRedirect(INDEX);
    }
	
	/**
	 * Resolves POST request with q parameter.
	 */
	public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException 
    {   
		// Check if the request has files.
		if(ServletFileUpload.isMultipartContent(request))
		{
			// Register User with image.
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setSizeThreshold(MAX_FILE_SIZE);

			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setFileSizeMax(MAX_UPLOAD_SIZE);
			upload.setSizeMax(MAX_FILE_SIZE);

			try
			{
				List<?> items = upload.parseRequest(request);
				Iterator<?> iter = items.iterator();
				
				String login = "";
				String password = "";
				String firstName = "";
				String lastName = "";
				String alias = "";
				FileItem image = null;
				
				// Iterate form fields
				while (iter.hasNext()) 
				{
				    FileItem item = (FileItem) iter.next();

				    if (item.isFormField()) 
				    {
				    	// Common form fields.
				    	if(item.getFieldName().equals(LOGIN))
				    	{
				    		login = item.getString();
				    	}
				    	else if(item.getFieldName().equals(PASSWORD))
				    	{
				    		password = item.getString();
				    	}
				    	else if(item.getFieldName().equals(FIRST_NAME))
				    	{
				    		firstName = item.getString();
				    	}
				    	else if(item.getFieldName().equals(LAST_NAME))
				    	{
				    		lastName = item.getString();
				    	}
				    	else if(item.getFieldName().equals(ALIAS))
				    	{
				    		alias = item.getString();
				    	}
				    }
				    else 
				    {
				    	// Image
				    	if(item.getFieldName().equals(PHOTO) && !item.getName().equals("") && item.getContentType().startsWith("image"))
				    	{
				    		image = item;
				    	}
				    }
				}
				
				// Create the user.
			    if(login.equals("") || password.equals("") || !Core.checkLogin(login) || (alias.equals("")?false:!Core.checkAlias(alias)))
			    {
			    	throw new ParameterException("Invalid parameters where given.");
			    }
			    else
			    {
			    	String name;
			    	
			    	if(image != null)
			    	{
			    		// Write images.
			    		String path = Core.getPath();
			    		name = login.replace(".", "");
			    		name = name.replace("com", "") + "." + image.getContentType().split("/")[1];
			    		File up = new File(path + "/temp/" + name);
			    		image.write(up);
			    		
			    		// Re check MIME type.
			    		MagicMimeMimeDetector md = new MagicMimeMimeDetector();
			    		Collection<?> c = md.getMimeTypesFile(up);
			    		
			    		Iterator<?> itr = c.iterator();
			    		while(itr.hasNext()) 
			    		{
			    			MimeType mt = (MimeType)itr.next();
			    			
			    			if(mt.getMediaType().startsWith("image"))
			    			{
			    				Crop.cropImage(up, path + "/profile", name, image.getContentType().split("/")[1]);
			    			}
			    			else
			    				name = DEFAULT_PHOTO;
			    			
			    			up.delete();
			    		}
			    	}
			    	else
			    		name = DEFAULT_PHOTO;
			    	
		    		// Sign up user.
		    		Core.registerUser(login, password, alias, firstName, lastName, name);
		    		
		    		// Create session.
		    		HttpSession s = request.getSession();
			    	s.setAttribute(LOGIN, login);
			    	s.setAttribute(ALIAS, (alias.equals("")? login: alias));
			    	s.setAttribute(PHOTO, name.equals("")? DEFAULT_PHOTO: name);
			    	s.setAttribute(FIRST_NAME, firstName);
			    	s.setAttribute(LAST_NAME, lastName);
			    	
			    	// Redirect.
			    	response.sendRedirect(INDEX);
			    }
			}
			catch(ParameterException pe)
			{
				pe.printStackTrace();	
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			}
			catch(Exception sde)
			{
				sde.printStackTrace();	
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			}
		}
		else
		{
			// This request has no files
			request.setCharacterEncoding("UTF-8");
			
			String function = request.getParameter(FUNCTION);
			
			if(function.equals(AUTHENTICATE))
			{
				try
				{
					// Authenticate a user.
					String login = request.getParameter(LOGIN);
					String password = request.getParameter(PASSWORD);
					
					if(login == null || password == null || login.equals("") || password.equals(""))
					{
						throw new ParameterException("Invalid parameters where given.");
					}
					
					response.setContentType("text/html");
					PrintWriter out = response.getWriter();
					User user = Core.authenticateUser(login, password);
					
					if(user != null)
					{
						HttpSession s = request.getSession();
				    	s.setAttribute(LOGIN, login);
				    	s.setAttribute(ALIAS, user.getAlias().equals("")? login: user.getAlias());
				    	s.setAttribute(PHOTO, user.getPhoto().equals("")? DEFAULT_PHOTO: user.getPhoto());
				    	s.setAttribute(FIRST_NAME, user.getFirstName());
				    	s.setAttribute(LAST_NAME, user.getLastName());
				    	
						out.print(OK);
					}
					else
					{
						out.print(NEGATIVE);
					}
					
					out.flush();
					out.close();
				}
				catch(ServerDownException sde)
				{
					sde.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
				catch(ParameterException pe)
				{
					pe.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
			}
			else if(function.equals(CHECK_LOGIN))
			{
				try
				{
					// Check a login's availability.
					String login = request.getParameter(LOGIN);
					
					if(login == null || login.equals(""))
					{
						throw new ParameterException("Null login was given.");
					}
					
					response.setContentType("text/html");
					PrintWriter out = response.getWriter();
					
					if(Core.checkLogin(login))
					{
						out.print(OK);
					}
					else
					{
						out.print(NEGATIVE);
					}
					
					out.flush();
					out.close();
				}
				catch(ServerDownException sde)
				{
					sde.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
				catch(ParameterException pe)
				{
					pe.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
			}
			else if(function.equals(CHECK_ALIAS))
			{
				try
				{
					// Check an alia's availability.
					String alias = request.getParameter(ALIAS);
					
					if(alias == null || alias.equals(""))
					{
						throw new ParameterException("Null alias was given.");
					}
					
					response.setContentType("text/html");
					PrintWriter out = response.getWriter();
					
					if(Core.checkAlias(alias))
					{
						out.print(OK);
					}
					else
					{
						out.print(NEGATIVE);
					}
					
					out.flush();
					out.close();
				}
				catch(ServerDownException sde)
				{
					sde.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
				catch(ParameterException pe)
				{
					pe.printStackTrace();	
					response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				}
			}
		}
	 }
}
